package com.atom.app.mvi.ui.compose

import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ParentDataModifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFontFamilyResolver
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.sp
import com.atom.app.mvi.R
import java.time.Duration
import java.time.LocalDateTime

val fontFamily = FontFamily(
    Font(R.font.montserrat_light, FontWeight.Light)
)

val SmallHeadingStyle = TextStyle(
    fontSize = 16.sp,
    fontWeight = FontWeight(600),
    letterSpacing = 0.5.sp,
    fontFamily = fontFamily
)

class TimeGraphParentData(
    val duration: Float,
    val offset: Float,
) : ParentDataModifier {
    override fun Density.modifyParentData(parentData: Any?) = this@TimeGraphParentData
}

enum class SleepTab(val title: Int) {
    Day(R.string.sleep_tab_day_heading),
    Week(R.string.sleep_tab_week_heading),
    Month(R.string.sleep_tab_month_heading),
    SixMonths(R.string.sleep_tab_six_months_heading),
    OneYear(R.string.sleep_tab_one_year_heading)
}

@SuppressLint("NewApi")
data class SleepGraphData(
    val sleepDayData: List<SleepDayData>,
) {
    val earliestStartHour: Int by lazy {
        sleepDayData.minOf { it.firstSleepStart.hour }
    }
    val latestEndHour: Int by lazy {
        sleepDayData.maxOf { it.lastSleepEnd.hour }
    }
}
@SuppressLint("NewApi")
data class SleepDayData(
    val startDate: LocalDateTime,
    val sleepPeriods: List<SleepPeriod>,
    val sleepScore: Int,
) {
    val firstSleepStart: LocalDateTime by lazy {
        sleepPeriods.sortedBy(SleepPeriod::startTime).first().startTime
    }
    val lastSleepEnd: LocalDateTime by lazy {
        sleepPeriods.sortedBy(SleepPeriod::startTime).last().endTime
    }
    val totalTimeInBed: Duration by lazy {
        Duration.between(firstSleepStart, lastSleepEnd)
    }

    val sleepScoreEmoji: String by lazy {
        when (sleepScore) {
            in 0..40 -> "😖"
            in 41..60 -> "😏"
            in 60..70 -> "😴"
            in 71..100 -> "😃"
            else -> "🤷‍"
        }
    }

    fun fractionOfTotalTime(sleepPeriod: SleepPeriod): Float {
        return sleepPeriod.duration.toMinutes() / totalTimeInBed.toMinutes().toFloat()
    }

    fun minutesAfterSleepStart(sleepPeriod: SleepPeriod): Long {
        return Duration.between(
            firstSleepStart,
            sleepPeriod.startTime
        ).toMinutes()
    }
}
@SuppressLint("NewApi")
data class SleepPeriod(
    val startTime: LocalDateTime,
    val endTime: LocalDateTime,
    val type: SleepType,
) {

    val duration: Duration by lazy {
        Duration.between(startTime, endTime)
    }
}
val Yellow_Awake = Color(0xFFffeac1)
val Yellow_Rem = Color(0xFFffdd9a)
val Yellow_Light = Color(0xFFffcb66)
val Yellow_Deep = Color(0xFFff973c)

enum class SleepType(val title: Int, val color: Color) {
    Awake(R.string.sleep_type_awake, Yellow_Awake),
    REM(R.string.sleep_type_rem, Yellow_Rem),
    Light(R.string.sleep_type_light, Yellow_Light),
    Deep(R.string.sleep_type_deep, Yellow_Deep)
}

@SuppressLint("NewApi")
val sleepData = SleepGraphData(
    listOf(
        SleepDayData(
            LocalDateTime.now().minusDays(7),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(21)
                        .withMinute(8),
                    endTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(21)
                        .withMinute(40),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(21)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(22)
                        .withMinute(20),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(22)
                        .withMinute(20),
                    endTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(7)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(1)
                        .withMinute(10),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(1)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(4)
                        .withMinute(10),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(4)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(5)
                        .withMinute(30),
                    type = SleepType.Awake
                )
            ),
            sleepScore = 90
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(6),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(22)
                        .withMinute(38),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(23)
                        .withMinute(55),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(6)
                        .withHour(23)
                        .withMinute(55),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(2)
                        .withMinute(40),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(2)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(2)
                        .withMinute(50),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(2)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(4)
                        .withMinute(12),
                    type = SleepType.Deep
                )
            ),
            sleepScore = 70
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(5),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(8),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(40),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(55),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(22)
                        .withMinute(55),
                    endTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(5)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(1)
                        .withMinute(10),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(1)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(3)
                        .withMinute(5),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(3)
                        .withMinute(5),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(4)
                        .withMinute(50),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(4)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(6)
                        .withMinute(30),
                    type = SleepType.REM
                )
            ),
            sleepScore = 60
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(4),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(20)
                        .withMinute(20),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(22)
                        .withMinute(40),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(22)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(23)
                        .withMinute(55),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(4)
                        .withHour(23)
                        .withMinute(55),
                    endTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(1)
                        .withMinute(33),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(1)
                        .withMinute(33),
                    endTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(3)
                        .withMinute(45),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(3)
                        .withMinute(45),
                    endTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(7)
                        .withMinute(15),
                    type = SleepType.Light
                )
            ),
            sleepScore = 90
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(3),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(3)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(0)
                        .withMinute(10),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(0)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(1)
                        .withMinute(10),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(1)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(4)
                        .withMinute(30),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(4)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(4)
                        .withMinute(45),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(4)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(4)
                        .withMinute(45),
                    type = SleepType.REM
                )
            ),
            sleepScore = 40
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(2),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(20)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(21)
                        .withMinute(40),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(21)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(22)
                        .withMinute(20),
                    type = SleepType.Light
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(22)
                        .withMinute(20),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(2)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(1)
                        .withMinute(10),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(1)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(4)
                        .withMinute(10),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(4)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(5)
                        .withMinute(30),
                    type = SleepType.Awake
                )
            ),
            sleepScore = 82
        ),
        SleepDayData(
            LocalDateTime.now().minusDays(1),
            listOf(
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(8),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(40),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(40),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(50),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(50),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(55),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(22)
                        .withMinute(55),
                    endTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(23)
                        .withMinute(30),
                    type = SleepType.REM
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .minusDays(1)
                        .withHour(23)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .withHour(1)
                        .withMinute(10),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .withHour(1)
                        .withMinute(10),
                    endTime = LocalDateTime.now()
                        .withHour(2)
                        .withMinute(30),
                    type = SleepType.Awake
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .withHour(2)
                        .withMinute(30),
                    endTime = LocalDateTime.now()
                        .withHour(3)
                        .withMinute(5),
                    type = SleepType.Deep
                ),
                SleepPeriod(
                    startTime = LocalDateTime.now()
                        .withHour(3)
                        .withMinute(5),
                    endTime = LocalDateTime.now()
                        .withHour(4)
                        .withMinute(50),
                    type = SleepType.Light
                )
            ),
            sleepScore = 70
        ),
    )
)
